package logic

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/gogap/logs"
	"github.com/shopspring/decimal"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"log"
	"math/rand"
	"strconv"
	"strings"
	"time"
	"yundian/internel/app/dao"
	"yundian/internel/app/dao/memberdao"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/helper/resphelper"
	"yundian/internel/app/models/automate"
	"yundian/internel/app/models/couponinfo"
	"yundian/internel/app/models/couponlog"
	"yundian/internel/app/models/devices"
	"yundian/internel/app/models/dividendslog"
	"yundian/internel/app/models/goods"
	"yundian/internel/app/models/membermodel"
	"yundian/internel/app/models/orders"
	"yundian/internel/app/models/paysetting"
	"yundian/internel/app/models/placemodel"
	"yundian/internel/app/models/ploys"
	"yundian/internel/app/models/prices"
	"yundian/internel/app/models/refunds"
	"yundian/internel/app/models/users"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
	"yundian/internel/pkg/utils"
	"yundian/internel/pkg/wechatpay"
	"yundian/internel/pkg/wxpay"
	"yundian/internel/pkg/wxpay/wxcrypto"
)

type WxNotifyLogic struct {
	WxConfig *paysetting.PaySetting
}

func NewNotifyLogic() *WxNotifyLogic {
	wxConfig := NewSettingLogic().GetPaySetting()
	return &WxNotifyLogic{WxConfig: wxConfig}
}

// ---------------------免押支付 -- 支付结果通知 业务逻辑处理------------------//
type detailData struct {
	Amount   string `json:"amount"`
	PaidTime string `json:"paid_time"`
}

// 创建支付分订单
func (wxLogic *WxNotifyLogic) CreatePayScoreOrder(resultData *wechatpay.PayData) bool {
	wc := NewSettingLogic().GetPaySettingByAppid(resultData.Get("appid"))
	memInfo := memberdao.NewMemberDao().GetMemberInfoByOpenidAndAppId(resultData.Get("openid"), wc.AppId).Unwrap().(*membermodel.MembersModel)
	devInfo := dao.NewDeviceDao().FetchDeviceInfoWithType(resultData.Get("attach")).Unwrap().(*devices.DeviceType)
	ployInfo := dao.NewPloysDao().GetPlacePloyInfo(devInfo.PlaceId, devInfo.SharedMode).Unwrap().(*ploys.PloyModel) // 获取商户最新奖励规则配置

	var uInfo *users.UserModel
	var isDraw, isTianhai int
	placeInfo := dao.NewPlaceDao().GetPlaceById(devInfo.PlaceId).Unwrap().(*placemodel.PlaceModel)     // 获取网点详情
	userInfo := dao.NewUserDao().GetUserInfoByPlaceId(devInfo.PlaceId).Unwrap().(*users.UserModel) // 获取用户详情
	uInfo = dao.GetParentUserInfoById(userInfo)

	isDraw = wxLogic.PloyWxOrder(memInfo, ployInfo, placeInfo)

	// 获取用户所属上级代理商
	if isDraw == 1 {
		if uInfo.ID == 0 { // 代理商被删除，不存在 或者协程的
			uInfo = dao.NewUserDao().GetUserInfoById(2).Unwrap().(*users.UserModel)
		} else {
			u := dao.GetLastDrawUserInfo(uInfo)                                  // 获取开启权益的代理商
			if u.ParentID == 0 && u.IsAdmin == 2 && placeInfo.BranchUserId > 0 { // 代理商都没开启
				uInfo = dao.NewUserDao().GetUserInfoById(placeInfo.BranchUserId).Unwrap().(*users.UserModel)
			} else {
				uInfo = u
			}
		}
	} else if isDraw == 2 {
		isDraw = 1
		isTianhai = 8
		uInfo = dao.NewUserDao().GetUserInfoById(2).Unwrap().(*users.UserModel)
	}
	log.Println("end-----------------------", isDraw, uInfo)

	timeRange := &struct {
		StartTime string `json:"start_time"`
		EndTime   string `json:"end_time"`
	}{}
	_ = json.Unmarshal([]byte(resultData.Get("time_range")), timeRange)
	stamp := wechatpay.ConvIntTime(timeRange.StartTime)
	money, _ := strconv.ParseInt(resultData.Get("total_amount"), 10, 64)

	// 1:等待下单 2:使用中 3:已撤销 4:交易失败 5:已完成 6:支付超时 7:待守约 10:已删除 11: 转入退款
	var status int8
	var stateDesc string
	switch resultData.Get("state") {
	case "CREATED":
		status = 1 // CREATED 商户已创建服务订单
		stateDesc = "商户已创建服务订单"
	case "DOING":
		status = 2 // DOING 服务订单进行中
		stateDesc = "服务订单进行中"
	case "DONE":
		status = 5 // DONE 服务订单完成
		stateDesc = "服务订单完成"
	case "REVOKED":
		status = 3 // REVOKED 商户取消服务订单
		stateDesc = "商户取消服务订单"
	case "EXPIRED":
		status = 4 // EXPIRED 服务订单已失效
		stateDesc = "服务订单已失效"
	}

	var productIdKey = utils.Join("productId-", resultData.Get("openid"), "-", resultData.Get("attach"))

	var payAt int64
	if stamp > 0 {
		payAt = stamp
	}

	m := orders.New().Mutate(
		orders.WithAppid(resultData.Get("appid")),
		orders.WithDeviceSn(resultData.Get("attach")),
		orders.WithMchid(resultData.Get("mchid")),
		orders.WithOpenid(resultData.Get("openid")),
		orders.WithOutTradeNo(resultData.Get("order_id")),  // 微信订单号
		orders.WithTradeNo(resultData.Get("out_order_no")), // 商户订单号
		//orders.WithPayAt(dingo.Time(stamp.Unix())),                        // 支付时间
		orders.WithPayAt(dingo.Time(payAt)), // 支付时间
		//orders.WithTradeType(resultData.Get("trade_type")),                    // 订单支付类型 - 微信支付分支付
		orders.WithTradeType("PreAuthPay"), // 订单支付类型 - 微信支付分支付
		orders.WithMoney(money),
		orders.WithMoneyStr(decimal.NewFromInt(money).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithTradeState(resultData.Get("state")), // 微信交易 状态
		orders.WithTradeStateDesc(stateDesc),           // 微信交易状态描述
		orders.WithTradeStateDoing(resultData.Get("state_description")),
		orders.WithCreateAt(dingo.Time(time.Now().Unix())),
		orders.WithState(status),
		orders.WithOrderFrom("weixin"),
		orders.WithPayFrom(1), // 1免押 2押金
		orders.WithMemberId(memInfo.UUID),
		orders.WithMemberName(memInfo.NickName),
		orders.WithMemberPhone(memInfo.Phone),
		orders.WithPlaceId(devInfo.PlaceId),
		orders.WithPlaceName(devInfo.PlaceName),
		orders.WithSharedMode(devInfo.SharedMode),
		orders.WithPayMoney(money),
		orders.WithPayMoneyStr(decimal.NewFromInt(money).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithTitle(devInfo.DeviceName),
		orders.WithFeeMode(int8(devInfo.FeeMode)),
		orders.WithPayType(3),
		orders.WithProductId(global.Rdb.Get(context.Background(), productIdKey).Val()),
		orders.WithIsDraw(int8(isDraw)),       // 1抽单 0不抽单
		orders.WithIsTianHai(int8(isTianhai)), // 0新系统  1天海
		orders.WithUserId(userInfo.ID),
		orders.WithUserName(userInfo.Name),
		orders.WithParentId(userInfo.ParentID),
		orders.WithAgentUserId(uInfo.ID),
		orders.WithKaUserId(userInfo.BranchUserId),
		orders.WithSettlementWay(1), // 未结算
		orders.WithProdType(devInfo.ProdType), // 设备类型  1  2  3
	)
	var b bool
	count := dao.NewOrderDao().CountOrderByTradeNo(resultData.Get("out_order_no")).Unwrap().(int64)
	if count > 0 {
		b = true
	} else {
		b = dao.NewOrderDao().InsertOrder(m).Unwrap().(bool)
	}
	return b
}

// 同步订单信息 - 完结
func (wxLogic *WxNotifyLogic) SyncOrderInfoComplete(param *wechatpay.PayData, endTime int64) bool {
	var status int8
	var stateDesc, stateDoning string
	stateDoning = param.Get("state_description")
	switch param.Get("state") {
	case "CREATED":
		status = 1 // CREATED 商户已创建服务订单
		stateDesc = "商户已创建服务订单"
	case "DOING":
		status = 2 // DOING 服务订单进行中
		stateDesc = "服务订单进行中"
		stateDoning = "COMPLETE"
	case "DONE":
		status = 5 // DONE 服务订单完成
		stateDesc = "服务订单完成"
	case "REVOKED":
		status = 3 // REVOKED 商户取消服务订单
		stateDesc = "商户取消服务订单"
	case "EXPIRED":
		status = 4 // EXPIRED 服务订单已失效
		stateDesc = "服务订单已失效"
	}
	collection := wechatpay.NewPayData()
	_ = collection.FromJsonStr(param.Get("collection"))
	// 状态 USER_PAYING：待支付 USER_PAID：已支付
	totalAmount, _ := strconv.ParseInt(collection.Get("total_amount"), 10, 64) // 总金额
	//paying_amount := apiData.Get("paying_amount") // 待支付金额
	paidAmount, _ := strconv.ParseInt(collection.Get("paid_amount"), 10, 64) // 已支付金额
	log.Println("订单状态，订单总金额， 支付金额", param.Get("state"), totalAmount, paidAmount)
	var details []map[string]interface{}
	_ = json.Unmarshal([]byte(collection.Get("details")), &details)
	var transactionId string
	if len(details) > 0 {
		transactionId = details[0]["transaction_id"].(string)
	}
	log.Println("打印测试订单详情", details)
	var s int8
	if param.Get("state") == "USER_PAYING" { // 待支付 --- 待守约
		s = 7
		m := orders.New()
		m.State = s // 订单状态
		m.Money = totalAmount
		m.MoneyStr = decimal.NewFromInt(totalAmount).Div(decimal.NewFromInt(100)).StringFixed(2)

		m.PayMoney = paidAmount
		m.PayMoneyStr = decimal.NewFromInt(paidAmount).Div(decimal.NewFromInt(100)).StringFixed(2)

		//m.PayAt = dingo.Time(wechatpay.ConvIntTime(fmt.Sprintf("%v", details[0]["paid_time"])))
		//m.SettlementState = 3
		//amount, _ := strconv.ParseInt(fmt.Sprintf("%v", details[0]["amount"]), 10, 64)
		//m.SettlementMoney = amount
		//m.SettlementMoneyStr = decimal.NewFromInt(amount).Div(decimal.NewFromInt(100)).StringFixed(2)
		m.TradeStateDesc = stateDesc
		m.TradeStateDoing = stateDoning
		m.TradeState = param.Get("state")
		m.TradeNo = param.Get("out_order_no")
		m.Openid = param.Get("openid")
		//m.EndAt = dingo.Time(endTime)
		m.OutTradeNo = transactionId

		b := dao.NewOrderDao().UpdateOrderByTradeNo(m).Unwrap().(bool)
		return b
	} else {
		s = status
		m := orders.New()
		m.State = s // 订单状态
		m.Money = totalAmount
		m.MoneyStr = decimal.NewFromInt(totalAmount).Div(decimal.NewFromInt(100)).StringFixed(2)

		m.PayMoney = paidAmount
		m.PayMoneyStr = decimal.NewFromInt(paidAmount).Div(decimal.NewFromInt(100)).StringFixed(2)

		m.PayAt = dingo.Time(wechatpay.ConvIntTime(fmt.Sprintf("%v", details[0]["paid_time"])))
		m.SettlementState = 3
		amount, _ := strconv.ParseInt(fmt.Sprintf("%v", details[0]["amount"]), 10, 64)
		m.SettlementMoney = amount
		m.SettlementMoneyStr = decimal.NewFromInt(amount).Div(decimal.NewFromInt(100)).StringFixed(2)
		m.TradeStateDesc = stateDesc
		m.TradeStateDoing = stateDoning
		m.TradeState = param.Get("state")
		m.TradeNo = param.Get("out_order_no")
		m.Openid = param.Get("openid")
		m.EndAt = dingo.Time(endTime)
		m.OutTradeNo = transactionId

		b := dao.NewOrderDao().UpdateOrderByTradeNo(m).Unwrap().(bool)
		return b
	}

}

// 同步订单信息 - 服务中
func (wxLogic *WxNotifyLogic) SyncOrderInfoServing(resultData *wechatpay.PayData) bool {
	memInfo := memberdao.NewMemberDao().
		GetMemberInfoByOpenidAndAppId(resultData.Get("openid"), resultData.Get("appid")).
		Unwrap().(*membermodel.MembersModel)

	var status int8
	var stateDesc, stateDoning string
	stateDoning = resultData.Get("state_description")
	switch resultData.Get("state") {
	case "CREATED":
		status = 1 // CREATED 商户已创建服务订单
		stateDesc = "商户已创建服务订单"
	case "DOING":
		status = 2 // DOING 服务订单进行中
		stateDesc = "服务订单进行中"
		stateDoning = "COMPLETE"
	case "DONE":
		status = 5 // DONE 服务订单完成
		stateDesc = "服务订单完成"
	case "REVOKED":
		status = 3 // REVOKED 商户取消服务订单
		stateDesc = "商户取消服务订单"
	case "EXPIRED":
		status = 4 // EXPIRED 服务订单已失效
		stateDesc = "服务订单已失效"
	}

	timeRange := &struct {
		StartTime string `json:"start_time"`
		EndTime   string `json:"end_time"`
	}{}
	_ = json.Unmarshal([]byte(resultData.Get("time_range")), timeRange)
	stamp := wechatpay.ConvIntTime(timeRange.StartTime)

	m := orders.New()
	m.State = status
	m.TradeStateDesc = stateDesc
	m.TradeStateDoing = stateDoning
	m.TradeState = resultData.Get("state")
	m.TradeNo = resultData.Get("out_order_no")
	m.Openid = resultData.Get("openid")
	m.MemberName = memInfo.NickName
	m.MemberPhone = memInfo.Phone
	m.MemberId = memInfo.UUID
	var payAt int64
	if stamp > 0 {
		payAt = stamp
	}
	m.PayAt = dingo.Time(payAt)

	b := dao.NewOrderDao().UpdateOrderByTradeNo(m).Unwrap().(bool)
	return b
}

// CalOrderDividends 计算订单分红
func (wxLogic *WxNotifyLogic) CalOrderDividends(apiData *wechatpay.PayData, endTime int64) {

	//var userInfo *users.UserModel
	orderInfo := dao.NewOrderDao().GetOrderInfoByTradeNo(apiData.Get("out_order_no")).Unwrap().(*orders.OrderModel)
	devInfo := dao.NewDeviceDao().FetchDeviceInfoWithType(orderInfo.DeviceSn).Unwrap().(*devices.DeviceType)
	collection := wechatpay.NewPayData()
	_ = collection.FromJsonStr(apiData.Get("collection"))
	settMoney, _ := strconv.ParseInt(collection.Get("paid_amount"), 10, 64) // 已支付金额

	NewOrderLogic().CalOrderDividends(orderInfo, devInfo, settMoney, endTime)

	//if orderInfo.IsDraw == helper.TypeNumIsDrawOpen {
	//	if orderInfo.AgentUserId <= 0 {
	//		logs.Error("CalOrderDividends->orderInfo.AgentUserId: 数据错误，无法执行分红", orderInfo)
	//		return
	//	}
	//	userInfo = dao.NewUserDao().GetUserInfoById(orderInfo.AgentUserId).Unwrap().(*users.UserModel)
	//} else {
	//	userInfo = dao.NewUserDao().GetUserInfoByPlaceId(orderInfo.PlaceId).Unwrap().(*users.UserModel)
	//}
	//
	//// 判断订单是否分红过
	//count := dao.NewOrderDao().CountDividendsLogsByTradeNo(orderInfo.TradeNo, userInfo.ID).Unwrap().(int64)
	//
	//// 没有分红
	//if count == 0 {
	//	// 计算上级代理商分红
	//	wxLogic.CalAgentBonus(userInfo, orderInfo, devInfo, settMoney, 0, endTime)
	//}
}

// CalAgentBonus 代理商分红

func (wxLogic *WxNotifyLogic) InsertRewardLog(tx *gorm.DB, curruserInfo *users.UserModel, orderInfo *orders.OrderModel, devInfo *devices.DeviceType, settMoney int64, money decimal.Decimal, endTime int64) error {
	dividends := &dividendslog.DividendsLog{}
	dividends.SharedMode = devInfo.SharedMode
	dividends.UserId = curruserInfo.ID
	dividends.UserName = curruserInfo.Name
	dividends.ProfitProportion = int8(curruserInfo.ProfitProportion)
	dividends.UpdateAt = dingo.Time(endTime)
	dividends.CreateAt = dingo.Time(endTime)
	dividends.ProfitType = int8(curruserInfo.ProfitType)
	dividends.PlaceId = orderInfo.PlaceId
	dividends.PlaceName = orderInfo.PlaceName
	dividends.TradeNo = orderInfo.TradeNo
	dividends.FeeMode = orderInfo.FeeMode

	dividends.State = 5 // 已完成
	fm, _ := money.Float64()
	dividends.Money = int64(fm)
	dividends.MoneyStr = money.Div(decimal.NewFromInt(100)).String() // 代理商获得的金额
	//dividends.MoneyStr = money.String() // 代理商获得的金额
	dividends.MemberName = orderInfo.MemberName
	dividends.MemberId = orderInfo.MemberId
	dividends.PayMoney = orderInfo.PayMoney
	dividends.PayMoneyStr = utils.Fen2Yuan(orderInfo.PayMoney)
	dividends.PayAt = orderInfo.PayAt
	dividends.SettlementAt = dingo.Time(time.Now().Unix())

	dividends.DeviceTypeName = devInfo.DeviceTypeName
	dividends.DeviceTypeID = devInfo.DeviceTypeId
	dividends.FeeMode = orderInfo.FeeMode
	dividends.DeviceSn = orderInfo.DeviceSn
	dividends.SettlementMoneyStr = utils.Fen2Yuan(settMoney)
	dividends.SettlementMoney = settMoney

	if result := dao.NewOrderDao().InsertDividends(tx, dividends); result.Err != nil {
		return result.Err
	}
	return nil
	//.Unwrap()
}

// 更新订单状态
func (wxLogic *WxNotifyLogic) UpdateOrderInfo(param ...interface{}) {
	orderId := param[0].(int)
	settResult := param[1].(*resphelper.SettlementResp)
	endTime := param[2].(int64)

	m := orders.New().Mutate(
		orders.WithId(orderId),
		orders.WithEndAt(dingo.Time(endTime)),            // 订单结束日期
		orders.WithState(5),                              // 订单状态status 5:已完成
		orders.WithRefundMoney(settResult.ReturnMoney),   // 退款金额
		orders.WithRefundAt(dingo.Time(endTime)),         // 退款时间
		orders.WithSettlementMoney(settResult.SettMoney), // 结算金额
		orders.WithSettlementMoneyStr(decimal.NewFromInt(settResult.SettMoney).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithSettlementState(3), // 3已结算
		orders.WithSettlementWay(1),   // 1微信支付

	)
	dao.NewOrderDao().UpdateOrder(m).Unwrap()
}

// ---------------------押金支付 -- 支付结果通知 业务逻辑处理------------------//

// 返回值信息
// [
// appid:wx9ab574042f46a487
// attach:
// bank_type:OTHERS
// cash_fee:10
// cash_fee_type:CNY
// device_info:0721YD04440
// fee_type:CNY
// is_subscribe:N
// mch_id:1600369044
// nonce_str:Y1pH9XDWmz0Bnqe7
// openid:oT10S5Y0_1tzX8GPsScExJ-cxhWI
// out_trade_no:20201128083922527895
// result_code:SUCCESS
// return_code:SUCCESS
// return_msg:OK
// sign:47E740E4E6954A88A4A0C79BC48CB06E4FEE8A3AD5327DEBF90FAB5B53B39E07
// time_end:20201128163943
// total_fee:10
// trade_state:SUCCESS
// trade_state_desc:支付成功
// trade_type:JSAPI
// transaction_id:4200000734202011289714693318
// ]

// 支付结果通知 业务逻辑处理    返回值 ： true处理成功通知
func (wxLogic *WxNotifyLogic) DepositPayResultNotify(resultData *wxpay.PayData) bool {
	count := dao.NewOrderDao().
		CountOrderByTradeNo(resultData.Get("out_trade_no")).
		Unwrap().(int64)

	// 验证订单是否已经处理
	if count > 0 { // 订单已处理
		return true
	}

	memInfo := memberdao.NewMemberDao().
		GetMemberInfoByOpenidAndAppId(resultData.Get("openid"), resultData.Get("appid")).
		Unwrap().(*membermodel.MembersModel)
	devInfo := dao.NewDeviceDao().FetchDeviceInfoWithType(resultData.Get("device_info")).Unwrap().(*devices.DeviceType)
	ruleInfo := dao.NewPricesDao().GetPriceDetail(resultData.Get("attach")).Unwrap().(*prices.PriceModel) // 获取产品ID对应的价格规则配置
	//ployInfo := dao.NewPloysDao().GetPlacePloyInfo(devInfo.PlaceId, devInfo.SharedMode).Unwrap().(*ploys.PloyModel) // 获取商户最新奖励规则配置

	var money int64

	if devInfo.FeeMode == 1 { // 计时
		money = ruleInfo.Deposit
	} else { // 套餐
		money = ruleInfo.PayMoney // 支付套餐价
	}

	// 验证订单价格是否正确
	wxMoney, _ := strconv.Atoi(resultData.Get("cash_fee"))
	if int64(wxMoney) != money { // 价格不一致
		log.Println("打印测试数据，价格不一致")
		zap.L().Error("微信支付结果通知,价格不一致")
		return true
	}

	// 创建订单 true创建成功 false创建失败
	orderCreateStatus := wxLogic.CreateOrder(
		resultData,
		devInfo,
		memInfo)
	// 更新设备 true 更新成功  false 更新失败
	_ = wxLogic.UpdateDeviceInfo(resultData) //更新设备信息 - 成功或失败不重要

	return orderCreateStatus
}

func (wxLogic *WxNotifyLogic) DepositPayResultNotifyV3(resultData *wechatpay.PayData, userId int) bool {
	count := dao.NewOrderDao().
		CountOrderByTradeNo(resultData.Get("out_trade_no")).
		Unwrap().(int64)
	if count > 0 {
		return true
	}

	var memInfo *membermodel.MembersModel
	if userId <= 0 {
		openId := wechatpay.NewPayData()
		_ = openId.FromJsonStr(resultData.Get("payer"))
		memInfo = memberdao.NewMemberDao().
			GetMemberInfoByOpenidAndAppId(openId.Get("openid"), resultData.Get("appid")).
			Unwrap().(*membermodel.MembersModel)
	} else {
		memInfo = memberdao.NewMemberDao().GetMemberInfoById(userId).Unwrap().(*membermodel.MembersModel)
	}

	devDT := wechatpay.NewPayData()
	_ = devDT.FromJsonStr(resultData.Get("scene_info"))
	devInfo := dao.NewDeviceDao().FetchDeviceInfoWithType(devDT.Get("device_id")).Unwrap().(*devices.DeviceType)
	logs.Info("打印测试========》设备ID", devDT.Get("device_id"))
	// 创建订单 true创建成功 false创建失败
	orderCreateStatus := wxLogic.CreateOrderV3(
		resultData,
		devInfo,
		memInfo)
	_ = wxLogic.UpdateDeviceInfoV3(devInfo.DeviceSn)

	return orderCreateStatus
}

func (wxLogic *WxNotifyLogic) DepositPayResultNotifyV3NoSmallDraw(resultData *wechatpay.PayData, userId int) bool {
	count := dao.NewOrderDao().
		CountOrderByTradeNo(resultData.Get("out_trade_no")).
		Unwrap().(int64)
	if count > 0 {
		return true
	}

	var memInfo *membermodel.MembersModel
	if userId <= 0 {
		openId := wechatpay.NewPayData()
		_ = openId.FromJsonStr(resultData.Get("payer"))
		memInfo = memberdao.NewMemberDao().
			GetMemberInfoByOpenidAndAppId(openId.Get("openid"), resultData.Get("appid")).
			Unwrap().(*membermodel.MembersModel)
	} else {
		memInfo = memberdao.NewMemberDao().GetMemberInfoById(userId).Unwrap().(*membermodel.MembersModel)
	}

	devDT := wechatpay.NewPayData()
	_ = devDT.FromJsonStr(resultData.Get("scene_info"))
	devInfo := dao.NewDeviceDao().FetchDeviceInfoWithType(devDT.Get("device_id")).Unwrap().(*devices.DeviceType)
	logs.Info("打印测试========》设备ID", devDT.Get("device_id"))
	// 创建订单 true创建成功 false创建失败
	orderCreateStatus := wxLogic.CreateOrderV3NoSmallDraw(
		resultData,
		devInfo,
		memInfo)
	_ = wxLogic.UpdateDeviceInfoV3(devInfo.DeviceSn)

	return orderCreateStatus
}

func (wxLogic *WxNotifyLogic) CouponPayScoreNotify(resultData *wechatpay.PayData) {
	//修改状态
	log.Println("支付分订单确认结果参数：", resultData)
	openid := resultData.Get("openid")
	tradeNo := resultData.Get("out_order_no")
	couponInfo := dao.NewCouponDao().GetCouponInfoOpenIdAndTradeNo(openid, tradeNo).Unwrap().(*couponinfo.CouponInfo)
	//有使用过的
	if couponInfo.Id == 0 {
		return
	}
	//resultData := param[0].(*wechatpay.PayData)
	//log.Println("支付分订单确认结果参数：", resultData)
	log.Println("订单编号", resultData.Get("out_order_no"), "openId", resultData.Get("openid"), "订单金额：", resultData.Get("paid_amount"))
	collection := wechatpay.NewPayData()
	_ = collection.FromJsonStr(resultData.Get("collection"))
	// 状态 USER_PAYING：待支付 USER_PAID：已支付
	totalAmount, _ := strconv.ParseInt(collection.Get("total_amount"), 10, 64) // 总金额
	paidAmount, _ := strconv.ParseInt(collection.Get("paid_amount"), 10, 64)   // 已支付金额

	//修改状态
	//couponInfo := dao.NewCouponDao().GetCouponInfoOpenId(resultData.Get("openid")).Unwrap().(*couponinfo.CouponInfo)
	//paid_amount
	couponInfoModel := couponInfo
	couponInfoModel.Status = 2
	couponInfoModel.OrderId = resultData.Get("out_order_no")
	orderMoney, _ := strconv.Atoi(resultData.Get("paid_amount"))
	dao.NewCouponDao().CouponInfoEditDao(couponInfo, orderMoney).Unwrap()

	//couponData := dao.NewCouponDao().GetCoupon(couponInfo.CId).Unwrap().(*coupon.Coupon)
	//新增日志
	couponLogModel := couponlog.CouponLog{}
	couponLogModel.CId = couponInfo.CId
	couponLogModel.UserId = couponInfo.UserId
	couponLogModel.OrderId = resultData.Get("out_order_no") // 对应订单标识
	couponLogModel.IsUse = 1                                //是否使用
	//wxMoney, _ := strconv.Atoi(resultData.Get("paid_amount"))
	couponLogModel.ActualMoney = int(totalAmount) - couponInfo.Discounts
	couponLogModel.OrderMoney = int(paidAmount)
	couponLogModel.FaceValue = couponInfo.Discounts

	if paidAmount > 0 || resultData.Get("out_order_no") != "" || resultData.Get("openid") != "" || couponInfo.CId > 0 || couponInfo.UserId > 0 {
		dao.NewCouponLogDao().CouponLogSaveDao(&couponLogModel).Unwrap()
	}
	//修改订单中的优惠券金额
	if resultData.Get("out_order_no") != "" {
		m := orders.New()
		m.TradeNo = resultData.Get("out_order_no")
		m.CouponMoney = int64(couponInfo.Discounts)
		m.CouponMoneyStr = decimal.NewFromInt(int64(couponInfo.Discounts)).Div(decimal.NewFromInt(100)).StringFixed(2)
		m.CouponType = int8(couponInfo.Id)
		//修改订单优惠券信息
		b := dao.NewOrderDao().UpdateOrderByTradeNo(m).Unwrap().(bool)
		if !b {
			log.Println(fmt.Sprintf("修改订单中的优惠券金额失败,OpenId%s,订单信息%v", resultData.Get("openid"), resultData))
		}
	} else {
		log.Println(fmt.Sprintf("修改订单中的优惠券金额失败,未知订单%s,OpenId%s,订单信息%v", resultData.Get("out_order_no"), resultData.Get("openid"), resultData))
	}

}

func (wxLogic *WxNotifyLogic) CouponDepositNotify(resultData *wxpay.PayData) {

	//resultData := param[0].(*wechatpay.PayData)
	log.Println("押金订单确认结果参数：", resultData)
	log.Println("订单编号", resultData.Get("out_trade_no"), "openId", resultData.Get("openid"), "订单金额：", resultData.Get("paid_amount"))
	//修改状态
	openid := resultData.Get("openid")
	tradeNo := resultData.Get("out_trade_no")
	couponInfo := dao.NewCouponDao().GetCouponInfoOpenIdAndTradeNo(openid, tradeNo).Unwrap().(*couponinfo.CouponInfo)
	//paid_amount
	couponInfoModel := couponInfo
	couponInfoModel.Status = 2
	couponInfoModel.OrderId = resultData.Get("out_trade_no")
	orderMoney, _ := strconv.Atoi(resultData.Get("paid_amount"))
	dao.NewCouponDao().CouponInfoEditDao(couponInfo, orderMoney).Unwrap()

	//couponData := dao.NewCouponDao().GetCoupon(couponInfo.CId).Unwrap().(*coupon.Coupon)
	//新增日志
	couponLogModel := couponlog.CouponLog{}
	couponLogModel.CId = couponInfo.CId
	couponLogModel.UserId = couponInfo.UserId
	couponLogModel.OrderId = resultData.Get("out_trade_no") // 对应订单标识
	couponLogModel.IsUse = 1                                //是否使用
	wxMoney, _ := strconv.Atoi(resultData.Get("paid_amount"))
	couponLogModel.ActualMoney = wxMoney - couponInfo.Discounts
	couponLogModel.OrderMoney = wxMoney
	couponLogModel.FaceValue = couponInfo.Discounts

	if wxMoney > 0 || resultData.Get("out_trade_no") != "" || resultData.Get("openid") != "" || couponInfo.CId > 0 || couponInfo.UserId > 0 {
		dao.NewCouponLogDao().CouponLogSaveDao(&couponLogModel).Unwrap()
	}

}

//func (wxLogic *WxNotifyLogic) CouponPayScoreNotify(resultData *wechatpay.PayData) {
//	//修改状态
//	couponInfo := dao.NewCouponDao().GetCouponInfoOpenId(resultData.Get("openid")).Unwrap().(*couponinfo.CouponInfo)
//	//paid_amount
//	param := &couponinfo.CouponInfo{}
//	param.Status = 2
//	param.OrderId = resultData.Get("out_trade_no")
//	dao.NewCouponDao().CouponInfoEditDao(couponInfo.Id, param).Unwrap()
//
//	couponData := dao.NewCouponDao().GetCoupon(couponInfo.CId).Unwrap().(*coupon.Coupon)
//	//新增日志
//	couponLogModel := couponlog.CouponLog{}
//	couponLogModel.CId = couponInfo.CId
//	couponLogModel.UserId = couponInfo.UserId
//	couponLogModel.OrderId = resultData.Get("out_trade_no") // 对应订单标识
//	couponLogModel.IsUse = 1                                //是否使用
//	wxMoney, _ := strconv.Atoi(resultData.Get("paid_amount"))
//	couponLogModel.ActualMoney = wxMoney
//	couponLogModel.OrderMoney = wxMoney + couponData.Discounts
//	dao.NewCouponLogDao().CouponLogSaveDao(&couponLogModel).Unwrap()
//
//}

// 微信订单奖励逻辑
func (wxLogic *WxNotifyLogic) PloyWxOrder(memInfo *membermodel.MembersModel, ployInfo *ploys.PloyModel, placeInfo *placemodel.PlaceModel) int {
	log.Println("进入----------------------------")
	isDraw := 0

	// wx_openid 微信公众号 openid  有在微信公众号登录过，就会在users表中存unionid，那么不抽单
	if memInfo.Unionid != "" {
		userInfo := dao.NewUserDao().GetUserInfoByUnionId(memInfo.Unionid).Unwrap().(*users.UserModel)
		if userInfo.ID > 0 {
			isDraw = 0
			return isDraw
		}
	}

	// 验证手机号码在users表中是否存在，存在则不抽单
	if memInfo.Phone != "" {
		userInfo := dao.NewUserDao().GetUserInfoByPhone(memInfo.Phone).Unwrap().(*users.UserModel)
		if userInfo.ID > 0 {
			isDraw = 0
			return isDraw
		}
	}

	// 判断商户有多少笔订单，20笔后才开始
	if c := dao.NewOrderDao().CountOrderByPlaceId(ployInfo.PlaceId).Unwrap().(int64); c <= 20 {
		isDraw = 0
		return isDraw
	}

	yysIndex, _ := global.Rdb.Incr(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"yysIndex").Result()
	if utils.Contains(strings.Split(placeInfo.DrawStr, ","), strconv.Itoa(int(yysIndex))) {
		isDraw = 2
		return isDraw
	}

	// 商户的奖励规则策略是否生效
	if ployInfo.Status == 1 { // 状态生效,那么开始抽单 ,后台如果停止策略则不抽单
		// 执行抽单算法 range范围  num奖励数
		var drawScopeArr []int // 生成抽单范围
		var drawArr []int      // 抽单结果
		var otherDrawArr []int // 抽单结果
		var drawIndex int64
		for i := 1; i <= ployInfo.Range; i++ {
			drawScopeArr = append(drawScopeArr, i)
		}
		drawNumber := ployInfo.Num // 抽单数
		currDrawNumber := ployInfo.Num
		// redis 获取商户抽单计数
		drawIndex, _ = global.Rdb.Incr(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawIndex").Result()
		//log.Println("当前商户抽单计数", drawIndex)
		// redis 获取商户被抽单的数组
		drawStr, _ := global.Rdb.Get(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawArr").Result()
		_ = json.Unmarshal([]byte(drawStr), &drawArr)
		//log.Println("当前商户要被抽单的数组", drawArr)
		if drawIndex == 1 || len(drawArr) == 0 {
			if ployInfo.Type == 1 {
				drawArr = wxLogic.regularDrawNumber(drawScopeArr, drawArr, otherDrawArr, drawNumber, currDrawNumber) // 1固定位置抽取
				//log.Println("固定抽单的数组", drawArr)
			}

			if ployInfo.Type == 2 {
				drawArr = wxLogic.randomDrawNumber(drawScopeArr, drawArr, drawNumber) // 2轮次随机抽取
				//log.Println("随机抽单数组", drawArr)
			}
			arr, _ := json.Marshal(drawArr)
			global.Rdb.Set(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawArr", string(arr), 0)
		}

		// 订单被抽中
		if utils.ContainsInt(drawArr, int(drawIndex)) {
			isDraw = 1
			return isDraw
		}

		// 计数超出抽单范围 重置计数
		if int(drawIndex) >= ployInfo.Range {
			global.Rdb.DecrBy(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawIndex", drawIndex)
			global.Rdb.Set(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawArr", "", 0)
		}
	}

	if yysIndex >= 100 {
		global.Rdb.DecrBy(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"yysIndex", yysIndex)
	}
	return isDraw
}

func (wxLogic *WxNotifyLogic) PloyWxOrderNoSmallDraw(memInfo *membermodel.MembersModel, ployInfo *ploys.PloyModel, placeInfo *placemodel.PlaceModel) int {
	log.Println("进入----------------------------")
	isDraw := 0

	// wx_openid 微信公众号 openid  有在微信公众号登录过，就会在users表中存unionid，那么不抽单
	if memInfo.Unionid != "" {
		userInfo := dao.NewUserDao().GetUserInfoByUnionId(memInfo.Unionid).Unwrap().(*users.UserModel)
		if userInfo.ID > 0 {
			isDraw = 0
			return isDraw
		}
	}

	// 验证手机号码在users表中是否存在，存在则不抽单
	if memInfo.Phone != "" {
		userInfo := dao.NewUserDao().GetUserInfoByPhone(memInfo.Phone).Unwrap().(*users.UserModel)
		if userInfo.ID > 0 {
			isDraw = 0
			return isDraw
		}
	}

	// 判断商户有多少笔订单，20笔后才开始
	if c := dao.NewOrderDao().CountOrderByPlaceId(ployInfo.PlaceId).Unwrap().(int64); c <= 20 {
		isDraw = 0
		return isDraw
	}

	// 商户的奖励规则策略是否生效
	if ployInfo.Status == 1 { // 状态生效,那么开始抽单 ,后台如果停止策略则不抽单
		// 执行抽单算法 range范围  num奖励数
		var drawScopeArr []int // 生成抽单范围
		var drawArr []int      // 抽单结果
		var otherDrawArr []int // 抽单结果
		var drawIndex int64
		for i := 1; i <= ployInfo.Range; i++ {
			drawScopeArr = append(drawScopeArr, i)
		}
		drawNumber := ployInfo.Num // 抽单数
		currDrawNumber := ployInfo.Num
		// redis 获取商户抽单计数
		drawIndex, _ = global.Rdb.Incr(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawIndex").Result()
		//log.Println("当前商户抽单计数", drawIndex)
		// redis 获取商户被抽单的数组
		drawStr, _ := global.Rdb.Get(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawArr").Result()
		_ = json.Unmarshal([]byte(drawStr), &drawArr)
		//log.Println("当前商户要被抽单的数组", drawArr)
		if drawIndex == 1 || len(drawArr) == 0 {
			if ployInfo.Type == 1 {
				drawArr = wxLogic.regularDrawNumber(drawScopeArr, drawArr, otherDrawArr, drawNumber, currDrawNumber) // 1固定位置抽取
				//log.Println("固定抽单的数组", drawArr)
			}

			if ployInfo.Type == 2 {
				drawArr = wxLogic.randomDrawNumber(drawScopeArr, drawArr, drawNumber) // 2轮次随机抽取
				//log.Println("随机抽单数组", drawArr)
			}
			arr, _ := json.Marshal(drawArr)
			global.Rdb.Set(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawArr", string(arr), 0)
		}

		// 订单被抽中
		if utils.ContainsInt(drawArr, int(drawIndex)) {
			isDraw = 1
			return isDraw
		}

		// 计数超出抽单范围 重置计数
		if int(drawIndex) >= ployInfo.Range {
			global.Rdb.DecrBy(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawIndex", drawIndex)
			global.Rdb.Set(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawArr", "", 0)
		}
	}

	return isDraw
}

//微信订单固定抽单
func (wxLogic *WxNotifyLogic) FixedPloyWxOrder(ployInfo *ploys.PloyModel) int {
	log.Println("进入----------------------------")
	isDraw := 0

	// 判断商户有多少笔订单，20笔后才开始
	if c := dao.NewOrderDao().CountOrderByPlaceId(ployInfo.PlaceId).Unwrap().(int64); c <= 20 {
		isDraw = 0
		return isDraw
	}

	yysIndex, _ := global.Rdb.Incr(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"yysIndex").Result()
	//log.Println("打印测试...计数", yysIndex)
	if utils.ContainsInt(global.Levels1, int(yysIndex)) {
		isDraw = 2
		return isDraw
	}

	// 商户的奖励规则策略是否生效
	if ployInfo.Status == 1 { // 状态生效,那么开始抽单 ,后台如果停止策略则不抽单
		// 执行抽单算法 range范围  num奖励数
		var drawScopeArr []int // 生成抽单范围
		var drawArr []int      // 抽单结果
		var otherDrawArr []int // 抽单结果
		var drawIndex int64
		for i := 1; i <= ployInfo.Range; i++ {
			drawScopeArr = append(drawScopeArr, i)
		}
		drawNumber := 8 // 抽单数
		currDrawNumber := 8

		// redis 获取商户抽单计数
		drawIndex, _ = global.Rdb.Incr(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawIndex").Result()
		log.Println("当前商户抽单计数", drawIndex)

		// redis 获取商户被抽单的数组
		drawStr, _ := global.Rdb.Get(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawArr").Result()
		_ = json.Unmarshal([]byte(drawStr), &drawArr)
		log.Println("当前商户要被抽单的数组", drawArr)

		if drawIndex == 1 || len(drawArr) == 0 {
			if ployInfo.Type == 1 {
				drawArr = wxLogic.regularDrawNumber(drawScopeArr, drawArr, otherDrawArr, drawNumber, currDrawNumber) // 1固定位置抽取
				log.Println("固定抽单的数组", drawArr)
			}

			if ployInfo.Type == 2 {
				drawArr = wxLogic.randomDrawNumber(drawScopeArr, drawArr, drawNumber) // 2轮次随机抽取
				log.Println("随机抽单数组", drawArr)
			}
			arr, _ := json.Marshal(drawArr)
			global.Rdb.Set(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawArr", string(arr), 0)
		}

		// 订单被抽中
		if utils.ContainsInt(drawArr, int(drawIndex)) {
			isDraw = 1
			return isDraw
		}

		// 计数超出抽单范围 重置计数
		if int(drawIndex) >= ployInfo.Range {
			global.Rdb.DecrBy(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawIndex", drawIndex)
			global.Rdb.Set(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"drawArr", "", 0)
		}
	}

	if yysIndex >= 100 {
		global.Rdb.DecrBy(context.Background(), strconv.Itoa(ployInfo.PlaceId)+"yysIndex", yysIndex)
	}
	return isDraw
}

// UpdateDeviceInfo 更新设备信息
func (wxLogic *WxNotifyLogic) UpdateDeviceInfo(respData *wxpay.PayData) bool {
	dm := devices.New().Mutate(
		devices.WithUpdateAt(dingo.Time(time.Now().Unix())),
		devices.WithStatus(3), //  3工作中
		devices.WithDeviceSn(respData.Get("device_info")),
	)
	if ok := dao.NewDeviceDao().UpdateDeviceBySn(dm).Unwrap().(bool); ok {
		return true
	}
	return false
}

// CreateOrder 生成订单 todo 需要添加KaUserId
func (wxLogic *WxNotifyLogic) CreateOrder(respData *wxpay.PayData, devInfo *devices.DeviceType, memInfo *membermodel.MembersModel) bool {
	stamp, _ := time.ParseInLocation("20060102150405", respData.Get("time_end"), time.Local)
	money, _ := strconv.ParseInt(respData.Get("total_fee"), 10, 64)
	payMoney, _ := strconv.ParseInt(respData.Get("cash_fee"), 10, 64)
	ployInfo := dao.NewPloysDao().GetPlacePloyInfo(devInfo.PlaceId, devInfo.SharedMode).Unwrap().(*ploys.PloyModel) // 获取商户最新奖励规则配置

	var uInfo *users.UserModel
	var isDraw, isTianhai int
	placeInfo := dao.NewPlaceDao().GetPlaceById(devInfo.PlaceId).Unwrap().(*placemodel.PlaceModel)     // 获取网点详情
	userInfo := dao.NewUserDao().GetUserInfoByPlaceId(devInfo.PlaceId).Unwrap().(*users.UserModel) // 获取用户详情
	uInfo = dao.GetParentUserInfoById(userInfo)

	isDraw = NewNotifyLogic().PloyWxOrder(memInfo, ployInfo, placeInfo)
	if isDraw == 1 {
		if uInfo.ID == 0 { // 代理商被删除，不存在
			uInfo = dao.NewUserDao().GetUserInfoById(2).Unwrap().(*users.UserModel)
		} else {
			u := dao.GetLastDrawUserInfo(uInfo)                                  // 获取开启权益的用户
			if u.ParentID == 0 && u.IsAdmin == 2 && placeInfo.BranchUserId > 0 { // 代理商都没开启
				uInfo = dao.NewUserDao().GetUserInfoById(placeInfo.BranchUserId).Unwrap().(*users.UserModel)
			} else {
				uInfo = u
			}
		}
	} else if isDraw == 2 {
		isDraw = 1
		isTianhai = 8
		uInfo = dao.NewUserDao().GetUserInfoById(2).Unwrap().(*users.UserModel)
	}

	// 查询当前商户属于哪个代理商或运营商
	//agentID := wxLogic.GetParentUserInfoById(userInfo.ParentID)
	//if agentID == 0 {
	//	agentID = 2
	//}
	//log.Println("代理商ID", agentID)
	// 1:等待下单2:使用中3:已撤销4:交易失败5:已完成6:支付超时7:待守约10:已删除
	var status int8
	switch respData.Get("trade_state") {
	case "SUCCESS":
		status = 2 // SUCCESS—支付成功  工作中
	case "REFUND":
		status = 11 // REFUND—转入退款
	case "NOTPAY":
		status = 1 // NOTPAY—未支付
	case "CLOSED":
		status = 9 // CLOSED—已关闭
	case "REVOKED":
		status = 3 // REVOKED—已撤销（刷卡支付）
	case "USERPAYING":
		status = 8 // USERPAYING--用户支付中
	case "PAYERROR":
		status = 4 // PAYERROR--支付失败(其他原因，如银行返回失败)
	}

	var payForm int8
	if respData.Get("trade_type") == "JSAPI" || respData.Get("trade_type") == "Normal" {
		payForm = 2
	}
	if respData.Get("trade_type") == "PreAuthPay" {
		payForm = 1
	}

	m := orders.New().Mutate(
		orders.WithAppid(respData.Get("appid")),
		orders.WithDeviceSn(respData.Get("device_info")),
		orders.WithMchid(respData.Get("mch_id")),
		orders.WithOpenid(respData.Get("openid")),
		orders.WithOutTradeNo(respData.Get("transaction_id")), // 微信订单号
		orders.WithTradeNo(respData.Get("out_trade_no")),      // 商户订单号
		orders.WithPayAt(dingo.Time(stamp.Unix())),            // 支付时间
		orders.WithBeginAt(dingo.Time(time.Now().Unix())),
		orders.WithTradeType(respData.Get("trade_type")), // 订单支付类型
		orders.WithMoney(money),
		orders.WithMoneyStr(decimal.NewFromInt(money).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithTradeState(respData.Get("trade_state")),          // 微信交易 状态
		orders.WithTradeStateDesc(respData.Get("trade_state_desc")), // 微信交易状态描述
		orders.WithCreateAt(dingo.Time(time.Now().Unix())),
		orders.WithBeginAt(dingo.Time(time.Now().Unix())),
		orders.WithState(status),
		orders.WithOrderFrom("weixin"),
		orders.WithPayFrom(payForm), // 1免押 2押金
		orders.WithMemberId(memInfo.UUID),
		orders.WithMemberName(memInfo.NickName),
		orders.WithMemberPhone(memInfo.Phone),
		orders.WithPlaceId(devInfo.PlaceId),
		orders.WithPlaceName(devInfo.PlaceName),
		orders.WithSharedMode(devInfo.SharedMode),
		orders.WithPayMoney(payMoney),
		orders.WithPayMoneyStr(decimal.NewFromInt(payMoney).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithTitle(respData.Get("title")),
		orders.WithIsDraw(int8(isDraw)), // 1抽单 0不抽单
		orders.WithProductId(respData.Get("attach")),
		orders.WithFeeMode(int8(devInfo.FeeMode)),

		orders.WithIsTianHai(int8(isTianhai)), // 0新系统  1天海
		orders.WithUserId(userInfo.ID),
		orders.WithUserName(userInfo.Name),
		orders.WithParentId(userInfo.ParentID),
		orders.WithKaUserId(userInfo.BranchUserId),
		orders.WithAgentUserId(uInfo.ID),
		orders.WithPayType(3),
		orders.WithSettlementWay(1), // 未结算
		orders.WithProdType(devInfo.ProdType), // 设备类型  1  2  3
		//orders.WithKaUserId(userInfo.ID), //分公司用户
	)
	if ok := dao.NewOrderDao().InsertOrder(m).Unwrap().(bool); ok { // 订单入库成功
		return true
	}
	return false
}

func (wxLogic *WxNotifyLogic) CreateOrderV3(respData *wechatpay.PayData, devInfo *devices.DeviceType, memInfo *membermodel.MembersModel) bool {
	ruleInfo := dao.NewPricesDao().GetPriceDetail(respData.Get("attach")).Unwrap().(*prices.PriceModel)
	ployInfo := dao.NewPloysDao().GetPlacePloyInfo(devInfo.PlaceId, devInfo.SharedMode).Unwrap().(*ploys.PloyModel) // 获取商户最新奖励规则配置

	var money int64
	if devInfo.FeeMode == 1 {
		money = ruleInfo.Deposit
	} else { // 套餐
		money = ruleInfo.PayMoney
	}
	dtAmount := wechatpay.NewPayData()
	_ = dtAmount.FromJsonStr(respData.Get("amount"))
	// 验证订单价格是否正确
	wxMoney, _ := strconv.Atoi(dtAmount.Get("total"))
	if int64(wxMoney) != money {
		logs.Info("打印测试数据，价格不一致")
		zap.L().Error("微信支付结果通知,价格不一致")
		return true
	}
	payMoney, _ := strconv.ParseInt(dtAmount.Get("payer_total"), 10, 64)

	//stamp, _ := time.ParseInLocation("20060102150405", respData.Get("time_end"), time.Local)
	//stampSuccessTime, _ := time.Parse("2006-01-02T15:04:05+08:00", respData.Get("success_time"))
	var bjlocal = time.FixedZone("Asia/Shanghai", 8*60*60)
	stampSuccessTime, _ := time.ParseInLocation("2006-01-02T15:04:05+08:00", respData.Get("success_time"), bjlocal)

	var uInfo *users.UserModel
	var isDraw, isTianhai int
	placeInfo := dao.NewPlaceDao().GetPlaceById(devInfo.PlaceId).Unwrap().(*placemodel.PlaceModel)     // 获取网点详情
	userInfo := dao.NewUserDao().GetUserInfoByPlaceId(devInfo.PlaceId).Unwrap().(*users.UserModel) // 获取用户详情
	uInfo = dao.GetParentUserInfoById(userInfo)
	isDraw = NewNotifyLogic().PloyWxOrder(memInfo, ployInfo, placeInfo)
	if isDraw == 1 {
		if uInfo.ID == 0 { // 代理商被删除，不存在
			uInfo = dao.NewUserDao().GetUserInfoById(2).Unwrap().(*users.UserModel)
		} else {
			u := dao.GetLastDrawUserInfo(uInfo)                                  // 获取开启权益的用户
			if u.ParentID == 0 && u.IsAdmin == 2 && placeInfo.BranchUserId > 0 { // 代理商都没开启
				uInfo = dao.NewUserDao().GetUserInfoById(placeInfo.BranchUserId).Unwrap().(*users.UserModel)
			} else {
				uInfo = u
			}
		}
	} else if isDraw == 2 {
		isDraw = 1
		isTianhai = 8
		uInfo = dao.NewUserDao().GetUserInfoById(2).Unwrap().(*users.UserModel)
	}


	// 1:等待下单2:使用中3:已撤销4:交易失败5:已完成6:支付超时7:待守约10:已删除
	var status int8
	switch respData.Get("trade_state") {
	case "SUCCESS":
		status = 2 // SUCCESS—支付成功  工作中
	case "REFUND":
		status = 11 // REFUND—转入退款
	case "NOTPAY":
		status = 1 // NOTPAY—未支付
	case "CLOSED":
		status = 9 // CLOSED—已关闭
	case "REVOKED":
		status = 3 // REVOKED—已撤销（刷卡支付）
	case "USERPAYING":
		status = 8 // USERPAYING--用户支付中
	case "PAYERROR":
		status = 4 // PAYERROR--支付失败(其他原因，如银行返回失败)
	}

	var payForm int8
	if respData.Get("trade_type") == "JSAPI" || respData.Get("trade_type") == "Normal" {
		payForm = 2
	}
	if respData.Get("trade_type") == "PreAuthPay" {
		payForm = 1
	}

	payerDt := wechatpay.NewPayData()
	_ = payerDt.FromJsonStr(respData.Get("payer"))
	m := orders.New().Mutate(
		orders.WithAppid(respData.Get("appid")),
		orders.WithDeviceSn(devInfo.DeviceSn),
		orders.WithMchid(respData.Get("mchid")),
		orders.WithOpenid(payerDt.Get("openid")),
		orders.WithOutTradeNo(respData.Get("transaction_id")), // 微信订单号
		orders.WithTradeNo(respData.Get("out_trade_no")),      // 商户订单号
		orders.WithProductId(respData.Get("attach")),

		orders.WithMemberId(memInfo.UUID),
		orders.WithMemberName(memInfo.NickName),
		orders.WithMemberPhone(memInfo.Phone),
		orders.WithPlaceId(devInfo.PlaceId),
		orders.WithPlaceName(devInfo.PlaceName),
		orders.WithSharedMode(devInfo.SharedMode),
		orders.WithFeeMode(int8(devInfo.FeeMode)),

		orders.WithMoney(money),
		orders.WithMoneyStr(decimal.NewFromInt(money).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithPayMoney(payMoney),
		orders.WithPayMoneyStr(decimal.NewFromInt(payMoney).Div(decimal.NewFromInt(100)).StringFixed(2)),

		orders.WithState(status),
		orders.WithTradeType(respData.Get("trade_type")), // 订单支付类型
		orders.WithTradeState(respData.Get("trade_state")),          // 微信交易 状态
		orders.WithTradeStateDesc(respData.Get("trade_state_desc")), // 微信交易状态描述
		orders.WithPayType(3),
		orders.WithSettlementWay(1), // 未结算
		orders.WithOrderFrom("weixin"),
		orders.WithPayFrom(payForm), // 1免押 2押金

		orders.WithPayAt(dingo.Time(stampSuccessTime.Unix())),            // 支付时间
		orders.WithBeginAt(dingo.Time(time.Now().Unix())),
		orders.WithCreateAt(dingo.Time(time.Now().Unix())),


		orders.WithIsDraw(int8(isDraw)), // 1抽单 0不抽单
		orders.WithIsTianHai(int8(isTianhai)), // 0新系统  1天海

		orders.WithUserId(userInfo.ID),
		orders.WithUserName(userInfo.Name),
		orders.WithParentId(userInfo.ParentID),
		orders.WithKaUserId(userInfo.BranchUserId),
		orders.WithAgentUserId(uInfo.ID),
		orders.WithProdType(devInfo.ProdType), // 设备类型  1  2  3

	)
	if ok := dao.NewOrderDao().InsertOrder(m).Unwrap().(bool); ok { // 订单入库成功
		return true
	}
	return false
}

func (wxLogic *WxNotifyLogic) CreateOrderV3NoSmallDraw(respData *wechatpay.PayData, devInfo *devices.DeviceType, memInfo *membermodel.MembersModel) bool {
	ruleInfo := dao.NewPricesDao().GetPriceDetail(respData.Get("attach")).Unwrap().(*prices.PriceModel)
	ployInfo := dao.NewPloysDao().GetPlacePloyInfo(devInfo.PlaceId, devInfo.SharedMode).Unwrap().(*ploys.PloyModel) // 获取商户最新奖励规则配置

	var money int64
	if devInfo.FeeMode == 1 {
		money = ruleInfo.Deposit
	} else { // 套餐
		money = ruleInfo.PayMoney
	}
	dtAmount := wechatpay.NewPayData()
	_ = dtAmount.FromJsonStr(respData.Get("amount"))
	// 验证订单价格是否正确
	wxMoney, _ := strconv.Atoi(dtAmount.Get("total"))
	if int64(wxMoney) != money {
		logs.Info("打印测试数据，价格不一致")
		zap.L().Error("微信支付结果通知,价格不一致")
		return true
	}
	payMoney, _ := strconv.ParseInt(dtAmount.Get("payer_total"), 10, 64)

	//stamp, _ := time.ParseInLocation("20060102150405", respData.Get("time_end"), time.Local)
	//stampSuccessTime, _ := time.Parse("2006-01-02T15:04:05+08:00", respData.Get("success_time"))
	var bjlocal = time.FixedZone("Asia/Shanghai", 8*60*60)
	stampSuccessTime, _ := time.ParseInLocation("2006-01-02T15:04:05+08:00", respData.Get("success_time"), bjlocal)

	var uInfo *users.UserModel
	var isDraw, isTianhai int
	placeInfo := dao.NewPlaceDao().GetPlaceById(devInfo.PlaceId).Unwrap().(*placemodel.PlaceModel)     // 获取网点详情
	userInfo := dao.NewUserDao().GetUserInfoByPlaceId(devInfo.PlaceId).Unwrap().(*users.UserModel) // 获取用户详情
	uInfo = dao.GetParentUserInfoById(userInfo)
	isDraw = NewNotifyLogic().PloyWxOrderNoSmallDraw(memInfo, ployInfo, placeInfo)
	if isDraw == 1 {
		if uInfo.ID == 0 { // 代理商被删除，不存在
			uInfo = dao.NewUserDao().GetUserInfoById(2).Unwrap().(*users.UserModel)
		} else {
			u := dao.GetLastDrawUserInfo(uInfo)                                  // 获取开启权益的用户
			if u.ParentID == 0 && u.IsAdmin == 2 && placeInfo.BranchUserId > 0 { // 代理商都没开启
				uInfo = dao.NewUserDao().GetUserInfoById(placeInfo.BranchUserId).Unwrap().(*users.UserModel)
			} else {
				uInfo = u
			}
		}
	}

	// 1:等待下单2:使用中3:已撤销4:交易失败5:已完成6:支付超时7:待守约10:已删除
	var status int8
	switch respData.Get("trade_state") {
	case "SUCCESS":
		status = 2 // SUCCESS—支付成功  工作中
	case "REFUND":
		status = 11 // REFUND—转入退款
	case "NOTPAY":
		status = 1 // NOTPAY—未支付
	case "CLOSED":
		status = 9 // CLOSED—已关闭
	case "REVOKED":
		status = 3 // REVOKED—已撤销（刷卡支付）
	case "USERPAYING":
		status = 8 // USERPAYING--用户支付中
	case "PAYERROR":
		status = 4 // PAYERROR--支付失败(其他原因，如银行返回失败)
	}

	var payForm int8
	if respData.Get("trade_type") == "JSAPI" || respData.Get("trade_type") == "Normal" {
		payForm = 2
	}
	if respData.Get("trade_type") == "PreAuthPay" {
		payForm = 1
	}

	payerDt := wechatpay.NewPayData()
	_ = payerDt.FromJsonStr(respData.Get("payer"))
	m := orders.New().Mutate(
		orders.WithAppid(respData.Get("appid")),
		orders.WithDeviceSn(devInfo.DeviceSn),
		orders.WithMchid(respData.Get("mchid")),
		orders.WithOpenid(payerDt.Get("openid")),
		orders.WithOutTradeNo(respData.Get("transaction_id")), // 微信订单号
		orders.WithTradeNo(respData.Get("out_trade_no")),      // 商户订单号
		orders.WithProductId(respData.Get("attach")),

		orders.WithMemberId(memInfo.UUID),
		orders.WithMemberName(memInfo.NickName),
		orders.WithMemberPhone(memInfo.Phone),
		orders.WithPlaceId(devInfo.PlaceId),
		orders.WithPlaceName(devInfo.PlaceName),
		orders.WithSharedMode(devInfo.SharedMode),
		orders.WithFeeMode(int8(devInfo.FeeMode)),

		orders.WithMoney(money),
		orders.WithMoneyStr(decimal.NewFromInt(money).Div(decimal.NewFromInt(100)).StringFixed(2)),
		orders.WithPayMoney(payMoney),
		orders.WithPayMoneyStr(decimal.NewFromInt(payMoney).Div(decimal.NewFromInt(100)).StringFixed(2)),

		orders.WithState(status),
		orders.WithTradeType(respData.Get("trade_type")), // 订单支付类型
		orders.WithTradeState(respData.Get("trade_state")),          // 微信交易 状态
		orders.WithTradeStateDesc(respData.Get("trade_state_desc")), // 微信交易状态描述
		orders.WithPayType(3),
		orders.WithSettlementWay(1), // 未结算
		orders.WithOrderFrom("weixin"),
		orders.WithPayFrom(payForm), // 1免押 2押金

		orders.WithPayAt(dingo.Time(stampSuccessTime.Unix())),            // 支付时间
		orders.WithBeginAt(dingo.Time(time.Now().Unix())),
		orders.WithCreateAt(dingo.Time(time.Now().Unix())),


		orders.WithIsDraw(int8(isDraw)), // 1抽单 0不抽单
		orders.WithIsTianHai(int8(isTianhai)), // 0新系统  1天海

		orders.WithUserId(userInfo.ID),
		orders.WithUserName(userInfo.Name),
		orders.WithParentId(userInfo.ParentID),
		orders.WithKaUserId(userInfo.BranchUserId),
		orders.WithAgentUserId(uInfo.ID),
		orders.WithProdType(devInfo.ProdType), // 设备类型  1  2  3

	)
	if ok := dao.NewOrderDao().InsertOrder(m).Unwrap().(bool); ok { // 订单入库成功
		return true
	}
	return false
}

func (wxLogic *WxNotifyLogic) UpdateDeviceInfoV3(deviceSn string) bool {
	dm := devices.New().Mutate(
		devices.WithUpdateAt(dingo.Time(time.Now().Unix())),
		devices.WithStatus(3), //  3工作中
		devices.WithDeviceSn(deviceSn),
	)
	if ok := dao.NewDeviceDao().UpdateDeviceBySn(dm).Unwrap().(bool); ok {
		return true
	}
	return false
}

// 固定抽单法
func (wxLogic *WxNotifyLogic) regularDrawNumber(drawScopeArr []int, drawArr []int, otherDrawArr []int, drawNumber int, currDrawNumber int) []int {
	var index = 1
	if len(drawArr) == currDrawNumber {
		println("退出递归：", len(drawArr))
		return drawArr
	}
	mod := len(drawScopeArr) / drawNumber
	for i := 0; i < len(drawScopeArr); i++ {
		// mod 等于1取值法
		if i == mod*index-1 {
			drawArr = append(drawArr, drawScopeArr[i])
			if mod == 1 {
				index = index + 2
			} else {
				index = index + 1
				if index > drawNumber {
					index = 1
				}
			}

		} else {
			otherDrawArr = append(otherDrawArr, drawScopeArr[i])
		}
	}
	drawScopeArr = otherDrawArr
	otherDrawArr = []int{}
	drawNumber = currDrawNumber - len(drawArr)

	return wxLogic.regularDrawNumber(drawScopeArr, drawArr, otherDrawArr, drawNumber, currDrawNumber)
}

// 随机抽单法
func (wxLogic *WxNotifyLogic) randomDrawNumber(drawScopeArr []int, drawArr []int, drawNumber int) []int {

	if len(drawArr) == drawNumber {
		println("退出递归：", len(drawArr))
		return drawArr
	}
	// 随机数
	rand.Seed(time.Now().UnixNano())

	// 随机抽取一单
	drawNum := drawScopeArr[rand.Intn(len(drawScopeArr))]

	//查重
	exist := false
	for _, v := range drawArr {
		if v == drawNum {
			exist = true
			break
		}
	}

	if !exist {
		drawArr = append(drawArr, drawNum)
	}

	//递归
	return wxLogic.randomDrawNumber(drawScopeArr, drawArr, drawNumber)
}

// ------------------------------ 退款结果 通知 ---------------------------------------- //

// 解密退款数据
func (wxLogic *WxNotifyLogic) RefundDataDeCrypto(reqInfo, apiKey string) (*wxpay.PayData, error) {
	// base64解码
	b, err := base64.StdEncoding.DecodeString(reqInfo)
	if err != nil {
		return nil, err
	}

	// 解密
	err = wxcrypto.SetAesKey(strings.ToLower(utils.Str2Md5(apiKey)))
	if err != nil {
		return nil, err
	}
	plaintext, err := wxcrypto.AesECBDecrypt(b) // plaintext 解密后的数据
	if err != nil {
		return nil, err
	}

	resultData := wxpay.NewPayData()
	err = resultData.XmlToData(plaintext)
	if err != nil {
		return nil, err
	}

	return resultData, nil
}

//[
//out_refund_no:YDR20210207131822964272
//out_trade_no:YD20210207131509579668
//refund_account:REFUND_SOURCE_RECHARGE_FUNDS
//refund_fee:80
//refund_id:50301007222021020706165499491
//refund_recv_accout:支付用户零钱
//refund_request_source:API
//refund_status:SUCCESS
//settlement_refund_fee:80
//settlement_total_fee:100
//success_time:2021-02-07 13:18:26
//total_fee:100
//transaction_id:4200000802202102072194534908
//]

func (wxLogic *WxNotifyLogic) RefundResultNotify(resultData *wxpay.PayData, appid, mchid string) bool {
	count := dao.NewRefundDao().
		CountRefundByRefundNo(resultData.Get("out_refund_no")).
		Unwrap().(int64)

	// 验证是否已经处理
	if count > 0 { // 已处理
		return true
	}
	//orderInfo := dao.NewOrderDao().GetOrderInfoByTradeNo(resultData.Get("out_trade_no")).Unwrap().(*orders.OrderModel)
	m := refunds.New()
	m.RefundNo = resultData.Get("out_refund_no")
	m.OutRefundNo = resultData.Get("refund_id")
	m.TradeNo = resultData.Get("out_trade_no")
	m.OutTradeNo = resultData.Get("transaction_id")

	m.RefundAccount = resultData.Get("refund_account")
	refundFee, _ := strconv.ParseInt(resultData.Get("refund_fee"), 10, 64)
	m.RefundFee = refundFee

	m.RefundRecvAccout = resultData.Get("refund_recv_accout")
	m.RefundRequestSource = resultData.Get("refund_request_source")
	m.RefundStatus = resultData.Get("refund_status")

	settlementRefundFee, _ := strconv.ParseInt(resultData.Get("settlement_refund_fee"), 10, 64)
	m.SettlementRefundFee = settlementRefundFee

	settlementTotalFee, _ := strconv.ParseInt(resultData.Get("settlement_total_fee"), 10, 64)
	m.SettlementTotalFee = settlementTotalFee

	m.SuccessTime = dingo.Time(wechatpay.StrTimeToInt(resultData.Get("success_time")))

	totalFee, _ := strconv.ParseInt(resultData.Get("total_fee"), 10, 64)
	m.TotalFee = totalFee

	m.Appid = appid
	m.Mchid = mchid

	m.CreateAt = dingo.Time(time.Now().Unix())
	m.UpdateAt = dingo.Time(time.Now().Unix())

	if ok := dao.NewRefundDao().InsertRefund(m).Unwrap().(bool); ok { // 入库成功
		// 更新订单表退款金额
		var total int64
		global.Orm.Raw("select sum(refund_fee) from refunds where trade_no = ?", resultData.Get("out_trade_no")).Find(&total)
		//money := decimal.NewFromInt(orderInfo.RefundMoney).Add(decimal.NewFromInt(refundFee)).IntPart()
		global.Orm.Exec("update orders set refund_money = ? where trade_no = ?", total, resultData.Get("out_trade_no"))
		return true
	}
	return false
}

func (wxLogic *WxNotifyLogic) RefundResultAutomateNotifyV3(resultData *wechatpay.PayData, appid, mchid string) bool {
	tradeNo := resultData.Get("out_trade_no")
	data := dao.NewAutomateDaoDao().GetAdminAutomateOrderInfoByTradeNo(tradeNo).Unwrap().(*automate.OrderModel)

	if data.Id <= 0 {
		return false
	}

	updateDb := &automate.OrderPayDb{
		OrderDb: automate.OrderDb{TradeNo: data.TradeNo, Status: helper.TypeNumOrderAutomateStatusWaitRevocation},
	}
	if db := dao.NewAutomateDaoDao().UpdateGoodsOrder(updateDb); db.Err != nil {
		zap.L().Error(db.Err.Error())
		return false
	}

	return true
}

func (wxLogic *WxNotifyLogic) RefundResultGoodsNotifyV3(resultData *wechatpay.PayData, appid, mchid string) bool {
	tradeNo := resultData.Get("out_trade_no")
	params := &request.SetGoodsOrderStatusReq{TradeNo: tradeNo, IsAdmin: helper.TypeNumIsAdminOperator}
	goodsOrderInfo := dao.NewGoodsDao().GetAdminGoodsOrdersInfo(params).Unwrap().(*goods.Orders)

	if goodsOrderInfo.Id <= 0 {
		return false
	}

	if err := dao.NewGoodsDao().UpdateGoodsOrdersAmount(tradeNo, 0); err != nil {
		zap.L().Error(err.Error())
		return false
	}

	return true

}

func (wxLogic *WxNotifyLogic) RefundResultRoomNotifyV3(resultData *wechatpay.PayData, appid, mchid string) bool {
	tradeNo := resultData.Get("out_trade_no")
	params := &request.SetRoomOrderStatusReq{TradeNo: tradeNo, IsAdmin: helper.TypeNumIsAdminOperator}
	OrderInfo := dao.NewRoomDaoDao().GetAdminRoomOrdersInfo(params).Unwrap().(*goods.Orders)

	if OrderInfo.Id <= 0 {
		return false
	}

	if err := dao.NewRoomDaoDao().UpdateRoomOrdersAmount(tradeNo, 0); err != nil {
		zap.L().Error(err.Error())
		return false
	}

	return true

}

//func (wxLogic *WxNotifyLogic) RefundResultNotifyV3(resultData *wechatpay.PayData, appid, mchid string) bool {
//	log.Println("生成退款记录")
//	//count := dao.NewRefundDao().
//	//	CountRefundByRefundNo(resultData.Get("out_refund_no")).
//	//	Unwrap().(int64)
//	//// 验证是否已经处理
//	//if count > 0 { // 已处理
//	//	return true
//	//}
//	orderInfo := dao.NewOrderDao().GetOrderInfoByOutTradeNo(resultData.Get("transaction_id")).Unwrap().(*orders.OrderModel)
//	refundsTotal := dao.NewOrderDao().GetRefundsByTransactionIdTotal(resultData.Get("transaction_id")).Unwrap().(int64)
//	amountMap := wechatpay.NewPayData()
//	amountMap.FromJsonStr(resultData.Get("amount"))
//	refundMoney, _ := strconv.ParseInt(amountMap.Get("refund"), 10, 64)
//	if orderInfo.PayMoney < refundsTotal+refundMoney {
//		return true
//	}
//
//	//amount:map[payer_refund:1000 payer_total:1000 refund:1000 total:1000]
//
//	log.Println("退款金额信息", amountMap)
//	//orderInfo := dao.NewOrderDao().GetOrderInfoByTradeNo(resultData.Get("out_trade_no")).Unwrap().(*orders.OrderModel)
//	m := refunds.New()
//	m.RefundNo = resultData.Get("out_refund_no")
//	m.OutRefundNo = resultData.Get("refund_id")
//	m.TradeNo = resultData.Get("out_trade_no")
//	m.OutTradeNo = resultData.Get("transaction_id")
//
//	m.RefundAccount = resultData.Get("refund_account")
//	refundFee, _ := strconv.ParseInt(amountMap.Get("refund"), 10, 64)
//	m.RefundFee = refundFee
//
//	m.RefundRecvAccout = resultData.Get("refund_recv_accout")
//	m.RefundRequestSource = resultData.Get("user_received_account")
//	m.RefundStatus = resultData.Get("refund_status")
//
//	settlementRefundFee, _ := strconv.ParseInt(amountMap.Get("payer_refund"), 10, 64)
//	m.SettlementRefundFee = settlementRefundFee
//
//	settlementTotalFee, _ := strconv.ParseInt(amountMap.Get("payer_total"), 10, 64)
//	m.SettlementTotalFee = settlementTotalFee
//
//	layout := "2006-01-02T15:04:05+08:00"
//	str := resultData.Get("success_time")
//	successTime, successTimeErr := time.Parse(layout, str)
//	if successTimeErr != nil {
//		log.Println("成功时间转化失败", successTimeErr, resultData.Get("success_time"))
//	}
//	m.SuccessTime = dingo.Time(successTime.Unix())
//
//	totalFee, _ := strconv.ParseInt(amountMap.Get("total"), 10, 64)
//	m.TotalFee = totalFee
//
//	m.Appid = appid
//	m.Mchid = mchid
//
//	m.CreateAt = dingo.Time(time.Now().Unix())
//	m.UpdateAt = dingo.Time(time.Now().Unix())
//
//	log.Println("退款记录字段：", m)
//
//	if ok := dao.NewRefundDao().InsertRefund(m).Unwrap().(bool); !ok { // 入库成功
//		// 更新订单表退款金额
//		//var total int64
//		//global.Orm.Raw("select sum(refund_fee) from refunds where trade_no = ?", resultData.Get("out_trade_no")).Find(&total)
//		//money := decimal.NewFromInt(orderInfo.RefundMoney).Add(decimal.NewFromInt(refundFee)).IntPart()
//		//global.Orm.Exec("update orders set refund_money = ? where trade_no = ?", total, resultData.Get("out_trade_no"))
//		return false
//	}
//
//	//查询退款总额
//	//refundsTotal := dao.NewOrderDao().GetRefundsByTransactionIdTotal(resultData.Get("transaction_id")).Unwrap().(int64)
//	dividends := orderInfo.PayMoney - (refundsTotal + refundMoney)
//	if dividends <= 0 {
//		log.Println("退款金额大于结算金额", orderInfo.TradeNo)
//		orderInfo.State = 3
//		dao.NewOrderDao().UpdateOrder(orderInfo).Unwrap()
//
//		NewOrderLogic().AgainStatistical(orderInfo.TradeNo)
//		//存在分红金额，删除之前分红数据
//		dao.NewOrderDao().DeleteDividendsLog(orderInfo.TradeNo).Unwrap()
//		return true
//	}
//
//	if dividends > 0 {
//		log.Println("部分退款金额回调：", orderInfo.TradeNo)
//		//存在分红金额，删除之前分红数据
//		dao.NewOrderDao().DeleteDividendsLog(orderInfo.TradeNo).Unwrap()
//
//		//查询订单对应的设备信息
//		deviceInfo := dao.NewOrderDao().GetDeviceInfo(orderInfo.DeviceSn).Unwrap().(*devices.DeviceType)
//		orderModel := &orders.OrderModel{}
//		orderModel.OutTradeNo = resultData.Get("transaction_id")
//		orderModel.SettlementMoney = dividends
//		orderModel.SettlementMoneyStr = decimal.NewFromInt(dividends).Div(decimal.NewFromInt(100)).StringFixed(2)
//		dao.NewOrderDao().UpdateOrderByOutTradeNo(orderModel).Unwrap()
//		//orderInfo.SettlementMoney = dividends
//		//dingo.Task(NewOrderLogic().CalOrderDividends, func() {}, orderInfo, deviceInfo, dividends, int64(orderInfo.EndAt)) // 计算分红 - 异步任务
//		NewOrderLogic().CalOrderDividends(orderInfo, deviceInfo, dividends, int64(orderInfo.EndAt)) //同步分红，
//		//修改统计，只修改金额不计算订单
//		NewOrderLogic().ByMoneyAgainStatistical(orderInfo.TradeNo)
//	}
//
//	return true
//
//}

// 递归查询
func (wxLogic *WxNotifyLogic) GetParentUserInfoById(parentId int) int {
	userInfo := dao.NewUserDao().GetUserInfoById(parentId).Unwrap().(*users.UserModel) // 获取上级的信息
	if userInfo.IsPlace == 0 && userInfo.IsAdmin == 2 {                                // 运营商
		return userInfo.ID
	} else if userInfo.IsPlace == 0 && userInfo.IsAdmin > helper.TypeNumIsAdminStaff { //代理商
		return userInfo.ID
	} else { // 商户
		wxLogic.GetParentUserInfoById(userInfo.ParentID)
	}
	return 0
}

// 微信通知解密
func (wxLogic *WxNotifyLogic) DecryptionNotifyLogic(reqInfo map[string]interface{}, apiKey string) (map[string]interface{}, error) {
	resourceByte, _ := json.Marshal(reqInfo)
	var cipherText, associatedData, nonceStr string
	var resource *wechatpay.Resource
	_ = json.Unmarshal(resourceByte, &resource)
	cipherText = resource.Ciphertext
	nonceStr = resource.Nonce
	associatedData = resource.AssociatedData
	resultData := map[string]interface{}{}
	dt, err := wechatpay.AesGcmDecrypt(cipherText, nonceStr, associatedData, apiKey)
	err = json.Unmarshal([]byte(dt), &resultData)
	if err != nil {
		return nil, err
	}

	return resultData, nil
}

// 解密退款数据
func (wxLogic *WxNotifyLogic) RefundDataDeCryptoV3(reqInfo map[string]interface{}, apiKey string) (*wechatpay.PayData, error) {
	resourceByte, _ := json.Marshal(reqInfo)
	var cipherText, associatedData, nonceStr string
	var resource *wechatpay.Resource
	_ = json.Unmarshal(resourceByte, &resource)
	cipherText = resource.Ciphertext
	nonceStr = resource.Nonce
	associatedData = resource.AssociatedData

	dt, err := wechatpay.AesGcmDecrypt(cipherText, nonceStr, associatedData, apiKey)

	resultData := wechatpay.NewPayData()
	err = resultData.FromJsonStr(dt)
	if err != nil {
		return nil, err
	}

	return resultData, nil
}

//&{map[amount:map[payer_refund:1 payer_total:30 refund:1 total:30]
//      mchid:1622892807
//      out_refund_no:ZMR20220330145655066699
//      out_trade_no:ZM20220330145530734460
//      refund_id:50301801362022033018806756440
//      refund_status:SUCCESS
//      success_time:2022-03-30T14:57:02+08:00
//      transaction_id:4200001355202203303083033681
//      user_received_account:支付用户零钱]}
func (wxLogic *WxNotifyLogic) RefundResultNotifyV3(resultData *wechatpay.PayData, appid, mchid string) bool {
	logs.Info("======== 生成退款记录 =========")
	orderInfo := dao.NewOrderDao().GetOrderInfoByOutTradeNo(resultData.Get("transaction_id")).Unwrap().(*orders.OrderModel) // 订单信息

	amountMap := wechatpay.NewPayData()
	_ = amountMap.FromJsonStr(resultData.Get("amount"))                       // 退款信息
	refundMoney, _ := strconv.ParseInt(amountMap.Get("refund"), 10, 64)       // 退款金额
	payerRefund, _ := strconv.ParseInt(amountMap.Get("payer_refund"), 10, 64) // 支付退款金额
	payerTotal, _ := strconv.ParseInt(amountMap.Get("payer_total"), 10, 64)   // 订单支付金额
	totalFee, _ := strconv.ParseInt(amountMap.Get("total"), 10, 64)           // 订单总金额

	m := refunds.New()
	m.RefundNo = resultData.Get("out_refund_no")    // 商户退款单号
	m.OutRefundNo = resultData.Get("refund_id")     // 微信退款号
	m.TradeNo = resultData.Get("out_trade_no")      // 商户订单号
	m.OutTradeNo = resultData.Get("transaction_id") // 微信支付单号
	m.RefundFee = refundMoney                       // 退款金额
	m.SettlementRefundFee = payerRefund             // 支付退款金额
	m.SettlementTotalFee = payerTotal               // 订单支付金额
	m.TotalFee = totalFee                           // 订单总金额

	m.RefundAccount = resultData.Get("refund_account")
	m.RefundRecvAccout = resultData.Get("refund_recv_accout")
	m.RefundRequestSource = resultData.Get("user_received_account") // 退款帐号
	m.RefundStatus = resultData.Get("refund_status")  // 退款状态

	layout := "2006-01-02T15:04:05+08:00"
	successTime, _ := time.Parse(layout, resultData.Get("success_time"))
	m.SuccessTime = dingo.Time(successTime.Unix())

	m.Appid = appid
	m.Mchid = mchid
	m.CreateAt = dingo.Time(time.Now().Unix())
	m.UpdateAt = dingo.Time(time.Now().Unix())

	c := dao.NewRefundDao().CountRefundByOutRefundNo(m.OutRefundNo).Unwrap().(int64)
	if c > 0 {
		logs.Info("======== 退款记录已存在 =========")
		return true
	}
	dao.NewRefundDao().InsertRefund(m).Unwrap()
	logs.Info("======== 退款记录新增成功 =========", orderInfo.PayMoney)

	// 计算结算金额
	refundsTotal := dao.NewOrderDao().GetRefundsByTransactionIdTotal(resultData.Get("transaction_id")).Unwrap().(int64)
	settlementMoney := decimal.NewFromInt(orderInfo.SettlementMoney).Sub(decimal.NewFromInt(refundsTotal)).IntPart()
	if settlementMoney <= 0 {
		dao.NewOrderDao().UpdateOrderState(orderInfo.Id, 3).Unwrap() // 更新订单状态
		dao.NewOrderDao().DeleteDividendsLog(orderInfo.TradeNo).Unwrap() // 删除分红
	} else {
		dao.NewOrderDao().UpdateOrderSettlementMoney(orderInfo.Id, settlementMoney).Unwrap() // 修改订单结算金额
		devInfo := dao.NewOrderDao().GetDeviceInfo(orderInfo.DeviceSn).Unwrap().(*devices.DeviceType)
		dao.NewOrderDao().DeleteDividendsLog(orderInfo.TradeNo).Unwrap() // 删除分红
		dingo.Task(NewOrderLogic().CalOrderDividends, func() {}, orderInfo, devInfo, settlementMoney, int64(orderInfo.EndAt))
	}
	return true
}
